<?php


namespace App\Repositories\Lottery;

use App\Traits\Singleton;
use App\Models\MainDB\Lottery\UserStatDate as Model;
use Illuminate\Support\Facades\DB;

class RankRepository
{
    use Singleton;

    public function luckyRank(int $userId, string $dateType, int $perPage = 10)
    {
        $userWhere   = $where = [
            ['created_at', '>=', $this->getDateStartTime($dateType)],
        ];
        $userWhere[] = ['user_id', '=', $userId];
        $lastCount   = 0;
        $index       = 1;
        $rank        = $this->notifyCountRank($where, $perPage)->transform(function ($item) use (&$index, &$lastCount) {
            $item->index = $index;
            $item->diff  = $index == 1 ? $lastCount : $lastCount - $item->count;
            ++$index;
            $lastCount = $item->count;
            return $item;
        });
        $user        = $this->notifyCountRank($userWhere, 1);
        if (!$user) {
            $user = Model::make([
                'user_id' => $userId,
                'count'   => 0,
                'index'   => 0,
            ]);
        }
        $userRank    = $rank->where('user_id', $userId)->first();
        $user->index = $userRank->index ?? 0;
        $user->diff  = $index == 1 ? $lastCount : $lastCount - $user->count;
        return Model::make(['rank' => $rank, 'self' => $user]);
    }

    public function one(array $condition = [], bool $fail = false, bool $lock = false)
    {
        $query = Model::query();
        $query->where($condition);
        if ($lock) {
            $query->lockForUpdate();
        }
        return $fail == true ? $query->firstOrFail() : $query->first();
    }

    public function find(int $id, bool $lock = false)
    {
        return $this->one(['id' => $id], true, $lock);
    }

    public function create(array $data)
    {
        $model = new Model();
        $model->fill($data);
        $model->save();
        $model->refresh();

        return $model;
    }

    protected function getDateStartTime(string $type): string
    {
        switch ($type) {
            case 'week':
                return date('Y-m-d 00:00:00', strtotime('this week Monday'));
            case 'month':
                return date('Y-m-01 00:00:00');
            default:
                return date('Y-m-d 00:00:00');
        }
    }

    protected function notifyCountRank(array $where, $perPage = 50)
    {
        $field = 'notify_count';
        $query = Model::query();
        $query->where($where);
        $query->where($field, '>', 0);
        $query->orderBy('count', 'desc');
        $query->groupBy(['user_id']);
        $query->select(['user_id', DB::raw("sum(`{$field}`) as count")]);
        $query->limit($perPage);
        return $perPage == 1 ? $query->first() : $query->with(['user.detail'])->get();
    }
}